#include <dirent.h>
#include <iostream>
#include <locale.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


#include "snow.h"
using namespace cv;
using namespace std;
/*********************************************************************************************************************************************************
*函数描述： snowException 计算并是否含有雪花的函数 vs_min 找出最小的那个数字
*函数参数： img 需要计算的图片，BGR存放格式，彩色（3通道），灰度图无效。
*原理：
    1.准备0°，45°，90°，135°4个方向的卷积模板。
    2.用图像先和四个模板做卷积，用四个卷积绝对值最小值Min来检测噪声点。
    3.求灰度图gray与其中值滤波图median。
    4.判断噪声点：fabs(median-gray)>10 && min>0.1。
    5. 噪声点占整幅图像的比较即为雪花噪声率。
*函数返回值： 返回值通过cast、da两个引用返回，无显式返回值
**********************************************************************************************************************************************************/
double vs_min(double a, double b, double c, double d) {
  double minn = 1000;
  if (a <= b) {
    minn = a;
  } else {
    minn = b;
  }
  if (minn > c) {
    minn = c;
  }
  if (minn > d) {
    minn = d;
  }
  return minn;
}
bool snowException(cv::Mat img) {
  Mat outImg1;
  Mat outImg2;
  Mat outImg3;
  Mat outImg4;
  Mat outMedian;
  Mat outGray;
  cvtColor(img, outGray, CV_BGR2GRAY);
  // cout<<outGray.channels()<<endl;
  Mat k0 = (Mat_<char>(3, 3) << 0, 0, 0, 1, 1, 1, 0, 0, 0);
  Mat k45 = (Mat_<char>(3, 3) << 0, 0, 1, 0, 1, 0, 1, 0, 0);
  Mat k90 = (Mat_<char>(3, 3) << 0, 1, 0, 0, 1, 0, 0, 1, 0);
  Mat k135 = (Mat_<char>(3, 3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
  // cout<<img.size()<<endl;
  filter2D(outGray, outImg1, outGray.depth(), k0);
  filter2D(outGray, outImg2, outGray.depth(), k45);
  filter2D(outGray, outImg3, outGray.depth(), k90);
  filter2D(outGray, outImg4, outGray.depth(), k135);
  medianBlur(outGray, outMedian, 3);
  // cout<<outMedian.size()<<endl;
  int width = img.cols; //图片宽度
  // cout<<width<<endl;
  int height = img.rows; //图片高度
  double vs = 0;
  double min_value = 10000;
  double snow = 0.0;
  double count = 0;
  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      vs = fabs(outMedian.at<uchar>(i, j) - outGray.at<uchar>(i, j));
      min_value =
          vs_min(fabs(outImg1.at<uchar>(i, j)), fabs(outImg2.at<uchar>(i, j)),
                 fabs(outImg3.at<uchar>(i, j)), fabs(outImg4.at<uchar>(i, j)));
      // cout<<"min_value"<<min_value<<endl;
      // cout<<"vs"<<vs<<endl;
      if (vs >= 10 && min_value > 0.1) {
        count++;
      }
    }
  }
  // cout<<count<<endl;
  snow = count / height / width;
  if (snow > 0.20) {
    printf("存在雪花！！！噪点率为:%f\n", snow);
    return true;
  }
  // else{
  // printf("画面正常，噪点率为:%f\n",snow);
  // }
  return false;
}
